package src.de.checker.hochzeit.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import src.de.checker.hochzeit.konstanten.Konstanten;
import src.de.checker.hochzeit.util.Datehelper;
import com.google.appengine.api.datastore.*;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;


public class AuthFilter implements Filter
{
	private static final Logger log = Logger.getLogger(AuthFilter.class.getName());
	
	private final String NO_ACCESS = "/noaccess";
	private final String INDEX = "/";
	private final String UPLOAD = "/_ah/upload/";
	
	private List<String> publicFunctions;
	private List<String> adminFunctions;
	private List<String> gastFunctions;
	private List<String> planerFunctions;
	private List<String> brautpaarFunctions;
	
	private long brautpaar = 0;
	private long planer = 1;
	private long gast = 2;
	
	@Override
	public void destroy() {
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest r = (HttpServletRequest)request;
		HttpSession s = r.getSession();
		
		String url = r.getRequestURI();
		String funktion = extractFunction(url);
		/*
		log.info("URL: "+url);
		log.info("Funktion: "+funktion);
		log.info("Session: "+s);*/
		
		//Keine für jeden zugängliche Funktion
		if(!getPublicFunctions().contains(funktion) && !url.startsWith(UPLOAD))
		{
			Entity myuser = getUser(s);
			Long userrole = (Long)getUserProperty(s, "rolle");
			//log.info("Benutzer: "+myuser);
			//log.info("Benutzerrolle: "+userrole);
			
			//Es ist kein Benutzer in der Session gesetzt
			if(myuser == null)
			{
				//Es wurde aber eine admin Funktion angefordert --> über googleuser geschutzt
				if(getAdminFunctions().contains(funktion))
					chain.doFilter(request, response);
				else
					((HttpServletResponse)response).sendRedirect(INDEX);
			}
			//Es ist ein Benutzer gesetzt
			else
			{
				if(userrole == null) //Der Benutzer hat aber keine Rolle
					((HttpServletResponse)response).sendRedirect(INDEX);
				//Der Benutzer hat die Rolle Gast
				else if(userrole.longValue() == gast) 
				{
					if(getGastFunctions().contains(funktion))
						chain.doFilter(request, response);
					else
					{
						makeTracer(url,request, myuser);
				        log.warning("ZUGRIFFS-SPERRE : "+getUserProperty(s, "loginname")+"für die URL: "+url);
						((HttpServletResponse)response).sendRedirect(NO_ACCESS);
					}
				}
				//Der Benutzer hat die Rolle Planer
				else if(userrole.longValue() == planer)
				{
					if(getPlanerFunctions().contains(funktion))
						chain.doFilter(request, response);
					else
					{
						makeTracer(url,request, myuser);
						log.warning("ZUGRIFFS-SPERRE : "+getUserProperty(s, "loginname")+"für die URL: "+url);
						((HttpServletResponse)response).sendRedirect(NO_ACCESS);
					}
				}
				//Der Benutzer hat die Rolle Brautpaar
				else if(userrole.longValue() == brautpaar)
				{
					if(getBrautpaarFunctions().contains(funktion))
						chain.doFilter(request, response);
					else
					{
						makeTracer(url,request, myuser);
						log.warning("ZUGRIFFS-SPERRE : "+getUserProperty(s, "loginname")+"für die URL: "+url);
						((HttpServletResponse)response).sendRedirect(NO_ACCESS);
					}
				}
				else
					((HttpServletResponse)response).sendRedirect(INDEX);
			}
		}
		else //Funktion ist für jeden zugänglich:
			chain.doFilter(request, response);
		
			
	}
	private void makeTracer(String url, ServletRequest request, Entity myuser)
	{
		try
		{
			DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			
			Entity t = new Entity(Konstanten.TRACER);
			t.setProperty("ipadresse", request.getRemoteAddr()) ;
			t.setProperty("user", myuser.getKey()) ;
			t.setProperty("nachricht", "ZUGRIFFS-SPERRE: URL "+url) ;
			t.setProperty("datum", Datehelper.getNow()) ;
			datastore.put(t);
	    }
		catch(Exception e)
		{
			log.warning("PROBLEME beim Speichern der Entity aus dem Authfilter");
			log.warning(e.toString());
		}
	}
	private Object getUserProperty(HttpSession s, String attr)
	{
		Entity user = getUser(s);
		if(user != null)
			return user.getProperties().get(attr);
		return null;
	}
	private Entity getUser(HttpSession s)
	{
		//log.info("Suche nach Nutzer unter: "+Konstanten.SESSION_USER);
		if(s != null && s.getAttribute(Konstanten.SESSION_USER) != null)
		{
			Entity user = (Entity)s.getAttribute(Konstanten.SESSION_USER);
			return user;
		}
		return null;
	}
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		
	}
	
	private String extractFunction(String url)
	{
		if(url.startsWith("/"))
		{
			if(url.equalsIgnoreCase("/"))
				return "index";
			String part_1 = url.substring(1,url.length());
			if(part_1.contains("/"))
			{
				return part_1.substring(0, part_1.indexOf("/"));
			}
			else
				return part_1;
		}
		return "";
	}
	public List<String> getPublicFunctions() 
	{
		if(publicFunctions == null)
		{
			publicFunctions = new ArrayList<String>();
			publicFunctions.add("index");
			publicFunctions.add("login");
			publicFunctions.add("noaccess");
			publicFunctions.add("favicon.ico");
			publicFunctions.add("registrieren");
			
		}
		return publicFunctions;
	}

	public List<String> getAdminFunctions() {
		if(adminFunctions == null)
		{
			adminFunctions = new ArrayList<String>();
			adminFunctions.add("admin");
			adminFunctions.add("_ah");
			adminFunctions.add("appstats");
		}
		return adminFunctions;
	}
	
	public List<String> getGastFunctions() {
		if(gastFunctions == null)
		{
			gastFunctions = new ArrayList<String>();
			gastFunctions.add("home");
			gastFunctions.add("peinstellungen");
			gastFunctions.add("peinstellungenk");
			gastFunctions.add("peinstellungenp");
			gastFunctions.add("pinnwand");
			gastFunctions.add("spiele");
			gastFunctions.add("photoalben");
		}
		return gastFunctions;
	}
	
	public List<String> getPlanerFunctions() {
		if(planerFunctions == null)
		{
			planerFunctions = new ArrayList<String>();
			planerFunctions.add("home");
			planerFunctions.add("gliste");
			planerFunctions.add("ideen");
			planerFunctions.add("orgap");
			planerFunctions.add("checkliste");
			planerFunctions.add("peinstellungen");
			planerFunctions.add("peinstellungenk");
			planerFunctions.add("peinstellungenp");
			planerFunctions.add("beinstellungen");
			planerFunctions.add("pinnwand");
			planerFunctions.add("spiele");
			planerFunctions.add("loc");
			planerFunctions.add("picture");
			planerFunctions.add("photoalben");
		}
		return planerFunctions;
	}
	
	public List<String> getBrautpaarFunctions() {
		if(brautpaarFunctions == null)
		{
			brautpaarFunctions = new ArrayList<String>();
			brautpaarFunctions.add("gaeste");
			brautpaarFunctions.add("home");
			brautpaarFunctions.add("ideen");
			brautpaarFunctions.add("checkliste");
			brautpaarFunctions.add("orga");
			brautpaarFunctions.add("heinstellungen");
			brautpaarFunctions.add("heinstellungenb");
			brautpaarFunctions.add("peinstellungen");
			brautpaarFunctions.add("peinstellungenp");
			brautpaarFunctions.add("peinstellungenk");
			brautpaarFunctions.add("pinnwand");
			brautpaarFunctions.add("spiele");
			brautpaarFunctions.add("locations");
			brautpaarFunctions.add("budget");
			brautpaarFunctions.add("zugang");
			brautpaarFunctions.add("album");
			brautpaarFunctions.add("photoalben");
		}
		return brautpaarFunctions;
	}

}
